#ifndef PALINDROME_INC
#define PALINDROME_INC

#include <iostream>
#include <string>
#include <cstring>
#include <mpi.h>

#include "Defines.h"
#include "Parser.h"

#define PALIN_SIZE    64

using namespace std;

/*
 * =====================================================================================
 *       Struct:  Palindrome
 *  Description:  Estrutura que representa um palíndromo
 * =====================================================================================
 */
typedef struct
{

    /*-----------------------------------------------------------------------------
     *  A palavra ou frase palíndroma
     *-----------------------------------------------------------------------------*/
    char palindrome[PALIN_SIZE];

    /*-----------------------------------------------------------------------------
     *  Boolean que diz se o palíndromo é primo
     *-----------------------------------------------------------------------------*/
    char isPrime;

} Palindrome;

typedef vector<Palindrome*> Palindromes;

/*
 * =====================================================================================
 *        Class:  PalindromeUtil
 *  Description:  Classe que faz algumas funções para palíndromos
 * =====================================================================================
 */
class PalindromeUtil
{

public:

    /*-----------------------------------------------------------------------------
     *  Contrói uma instância passando o modo
     *-----------------------------------------------------------------------------*/
    PalindromeUtil(bool printPrime);

    /*-----------------------------------------------------------------------------
     *  Destrói a instância
     *-----------------------------------------------------------------------------*/
    virtual ~PalindromeUtil();

    /*-----------------------------------------------------------------------------
     *  Procura por palíndromos em uma sequência de palavras ou frases
     *-----------------------------------------------------------------------------*/
    Palindromes *checkForPalindromes(const Tokens *tokens);

    /*-----------------------------------------------------------------------------
     *  Imprime os palíndromos
     *-----------------------------------------------------------------------------*/
    void printPalindromes(bool printPrime);

    /*-----------------------------------------------------------------------------
     *  Imprime todos os palíndromos
     *-----------------------------------------------------------------------------*/
    friend ostream& operator<<(ostream& os, PalindromeUtil &putil);

    /*-----------------------------------------------------------------------------
     *  Retorna quantidade de palindromos
     *-----------------------------------------------------------------------------*/
    int getSize();

    /*-----------------------------------------------------------------------------
     *  Incrementa a quantidade de números primos
     *-----------------------------------------------------------------------------*/
    void incNPrimes(uint sum);

    /*-----------------------------------------------------------------------------
     *  Retorna quantidade de números primos encontrados
     *-----------------------------------------------------------------------------*/
    int getNPrimes();

    /*-----------------------------------------------------------------------------
     *  Envia os palíndromos para um destino
     *-----------------------------------------------------------------------------*/
    void sendTo(int dest);

    /*-----------------------------------------------------------------------------
     *  Recebe os palíndromos de uma fonta
     *-----------------------------------------------------------------------------*/
    void receiveFrom(int src);


private:

    /*-----------------------------------------------------------------------------
     *  Verifica se a string passada é um palíndromo
     *-----------------------------------------------------------------------------*/
    bool isPalindrome(const string& s);

    /*-----------------------------------------------------------------------------
     *  Verifica se a soma ASCII da palavra é um número primo
     *-----------------------------------------------------------------------------*/
    bool isSumAPrimeNumber(const string& s);

    /*-----------------------------------------------------------------------------
     *  Vetor aonde será armazenado todos os palíndromes encontrados
     *-----------------------------------------------------------------------------*/
    Palindromes *palins;

    /*-----------------------------------------------------------------------------
     *  Boolean que indica se é para imprimir os números primos
     *-----------------------------------------------------------------------------*/
    bool printPrime;

    /*-----------------------------------------------------------------------------
     *  Quantidade de números primos encontrados
     *-----------------------------------------------------------------------------*/
    int nPrimes;

};

#endif /* ----- #ifndef PALINDROME_INC  ----- */
